/*!
	\file  main.c
	\brief GPIO running led

	\version 2014-12-26, V1.0.0, demo for GD32F10x
	\version 2017-06-30, V2.0.0, demo for GD32F10x
	\version 2018-07-31, V2.1.0, demo for GD32F10x
*/

/*
	Copyright (c) 2018, GigaDevice Semiconductor Inc.

	All rights reserved.

	Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

	1. Redistributions of source code must retain the above copyright notice, this
	   list of conditions and the following disclaimer.
	2. Redistributions in binary form must reproduce the above copyright notice,
	   this list of conditions and the following disclaimer in the documentation
	   and/or other materials provided with the distribution.
	3. Neither the name of the copyright holder nor the names of its contributors
	   may be used to endorse or promote products derived from this software without
	   specific prior written permission.

	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "app.h"
#include "gd32f10x.h"
#include "general_config.h"
#include "systick.h"
#include "TFT_LCD.h"
#include "lcd_app.h"
#include "Beep.h"
#include "key.h"
/****************debug***********************************/
uint16_t debug_PowerCheck, debug_AirPress2;
int16_t debug_humidity;
/****************debug***********************************/
flag_t Flag;
uint8_t vave1_SetPosi, vave2_SetPosi;
double threshold;

extern uint8_t RED_FIG;
volatile uint8_t Beepstop_Flg = 0;//蜂鸣器停止标志位

volatile uint8_t Power_stop_Flg = 0;//断电标志位 “1”断电  /  “2”正常供电

void Beep_Led_Init()
{
	rcu_periph_clock_enable(RCU_GPIOB);															   //使能GPIO口时钟  推挽输出
	gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_14 | GPIO_PIN_15); //推挽输出
	gpio_bit_set(GPIOB, GPIO_PIN_8);
	gpio_bit_set(GPIOB, GPIO_PIN_14); //默认高电平
	gpio_bit_set(GPIOB, GPIO_PIN_15); //默认高电平
	gpio_bit_reset(GPIOB, GPIO_PIN_9); //默认低电平
//	adjust_volume(0);
	KeyBackLed_ON();
}

void MotorInit() //转动电机
{
	rcu_periph_clock_enable(RCU_GPIOE); //使能GPIO口时钟  推挽输出
	gpio_init(MOTOR1_GPIO_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, MOTOR1_PIN);
	// gpio_init(MOTOR2_GPIO_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, MOTOR2_PIN);
	gpio_bit_reset(MOTOR1_GPIO_PORT, MOTOR1_PIN); //默认低电平
	// gpio_bit_reset(MOTOR2_GPIO_PORT, MOTOR2_PIN);
}
void PumpInit() //泵电机
{
	/* enable the PIN clock */
	rcu_periph_clock_enable(RCU_GPIOE);
	// IO输出
	/* configure PIN GPIO port */ //推挽输出
	gpio_init(PUMP1_GPIO_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, PUMP1_PIN);
	// gpio_init(PUMP2_GPIO_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, PUMP2_PIN);

	/* turn off the PIN */
	gpio_bit_reset(PUMP1_GPIO_PORT, PUMP1_PIN); //默认低电平
	// gpio_bit_reset(PUMP2_GPIO_PORT, PUMP2_PIN);
}
void PARA_INIT()
{
	Flag.LockCnt = def_lock;					 //#define def_lock 30000   //锁键时间 30s(最大32767)
	SettingPARA.powON = 1;						 //默认开机
	SettingPARA.hight = def_hight;				 // 170  身高
	SettingPARA.weight = def_weight;			 // 70  体重
	// SettingPARA.TurnCycle_lenth = def_turnlenth; // 30 翻身时间
	SettingPARA.WaveCycle_lenth = def_wavelenth; // 10 波动时间
	SettingPARA.mode = MODE_STATIC;				 // 0  静态模式
	CurrentPARA.air_column = 3;					 //当前气柱 2条都充气
	CurrentPARA.inbed = 0;						 //在离床
	vave1_SetPosi = limit2;						 // 2 初始值 泵开始工作
	// vave2_SetPosi = limit4;						 // 4 初始值 泵开始工作

	BMI = (double)(SettingPARA.hight * SettingPARA.hight) / (double)10000.0; // PARA数据平台设置下发的
	BMI = (double)(SettingPARA.weight) / BMI;
	threshold = calc_airpress(); //初始压力值
}
//后续需要添加：充气管子 CPR等功能完善。充气时间报警问题。压力垫一些跟mqtt报警连接等信息。
int main(void)
{
	const uint8_t wifi_reset[] = {0XA5, 0X5A, 0X00, 0X01, 0XAA};

	nvic_vector_table_set(NVIC_VECTTAB_FLASH, 0x4000);
	systick_config();
	timer5_init(3599, 29); // 108M 分频3600，1ms    Tout=((arr+1)*(psc+1))/Ft us.
	timer2_init();//给蜂鸣器模块使用的定时器

	/*各种GPIO初始化*/
	key_init();		 // 8个按键初始化
	limit_sw_init(); //微动开关初始化
	LCD_GPIO_INIT(); // LCD显示初始化
	MotorInit();	 //电机初始化
	PumpInit();		 //泵初始化
	Beep_Led_Init(); //蜂鸣器跟灯初始化
	/*usart2初始化*/
	usart2_config(); // WIFI
	//usart1_config(); //压力垫
	/*DMA初始化*/
	adc_dma_config(); // 2个气体传感器检测+断电检测+尿湿报警（现在用作检测有无压力垫）
	usart_dma_config();
	/*ADC初始化*/
	adc_config();

	//	AFIO_PCF0 = (AFIO_PCF0 & 0xF8FFFFFF) | 0x02000000;

	TFTLCD_Init(); //显示屏初始化
	WIFI_INIT();   // wifi初始化
	PARA_INIT();   //默认值初始化 身高 体重 模式 泵限位值 等初始化
	show_list();   //显示条初始化  第一次开机画面

	while (1)
	{
		Power_stop_beep();

		if (Flag.KeyScanFlag) //获取按键标志  20ms后更改为1
		{
			/****************debug***********************************/
			//		debug_AlirPress2=ADC_AirPress2();
			debug_humidity = ADC_humidity(); //尿湿检测（现在用作检测有无压力垫） 是否返回压力数值
			//压力传感插上才运行压力垫程序
			if (debug_humidity >= 0)
			{
				if (debug_humidity > 3100) // 2.5V左右
				{
					Flag.PressSensOn = 1; //压力传感插入
				}
				else
				{
					Flag.PressSensOn = 0; //压力传感没有插入
				}
			}
			Flag.PressSensOn = 1; //压力传感插入

			//		debug_PowerCheck=ADC_PowerCheck();
			//		debug_adc();
			/****************debug***********************************/

			SW_Process(); //按键扫描--轮询
			Flag.KeyScanFlag = 0;
		}

		ReceiveHdl();				//判断wifi模块连接状态
		SetDown();					//设置身高体重开关机等信息（跳转其他界面起作用）
		if (1 == CurrentPARA.powON) //判断是否开机状态
		{
			ModeHdl();	//气柱
			// TurnHdl();	//翻身
			warn_hdl(); //报警

			Sound_off_icon();//声音图标

			Low_pressure_alarm();//低压报警

			pressureStateMachine();//屏幕右上角低压与正常显示
		}
		else
		{
		}

		Valve1Move(vave1_SetPosi); //阀1位置  第一次值 2
		// Valve2Move(vave2_SetPosi); //阀2位置  第一次值 4
		//Flag.mqtt_conected = 1;
#if Debug_Stop_Tump_MQTT 
		Flag.mqtt_conected = 1;
		Flag.route_conected = 1;
		if (1) //
#else
		if (1 == Flag.mqtt_conected && 0 == UartSendDelay) //连接上MQTT时---100ms进来一次
#endif
		{
			if (Flag.timer_1s) // 1s一次发状态
			{
				//delay_1ms(50);
				sendHealthInfo();       //上报json信息    health主题
				delay_1ms(50);
				SendHdl(); 
				delay_1ms(50);               //往esp32发   data主题
				warn_data();
				//sendhumanbody_data();  //发送身高体重数据
				delay_1ms(50);
				//sendpress_data();     //发送压力数据
				Flag.timer_1s = 0;
				UartSendDelay = 100; // ms
			}                                                                                                                                     
			else
			{
				if (1 == Flag.SendFWInfo)
				{
					sendFirmwareInfo(); //固件升级时候的版本信息 
					Flag.SendFWInfo = 0;
				}
				// NOTE: 测试上报health消息
				// if (1 == rx1_frame_OK) // debug
				// {
				// 	sendHealthInfo(); //上报jason信息
				// 	rx1_frame_OK = 0;
				// }
#if Debug_Stop_Tump_MQTT
				if (1 == Flag.PressSensOn) //压力传感器无压力数据     没 插上的前提下
#else
				if (1 == Flag.PressSensOn)				   //压力传感器无压力数据   压力传感器插上的前提下
#endif
				{
					if (1 == rx1_frame_OK) //压力垫  串口1数据接收完成
					{
						//delay_1ms(50);
						//bodystatus();          // 判断是否在离床  压力垫接收数据求和
						// getPressprofile();
						//PressValue_SendHandle();								            //压力数据发送给平台
					//	dma_transfer_number_config(DMA0, DMA_CH5, rx1_buffersize);    //采集数据，初始化  压力垫数据
						//dma_channel_enable(DMA0, DMA_CH5);						      //使能DMA
						rx1_frame_OK = 0;
						pressTimeoutCnt = 0;
						UartSendDelay =100; // 100ms延时
					}
				}
				else
				{
					pressTimeoutCnt = 0;
					rx1_frame_OK = 0;
				}
				SendCalibrtion(); //发送校准信息  20S校准一次  发给ESP32
			}
			
		}
		else if (0 == Flag.mqtt_conected && 1 == Flag.wifiReset) // wifi重置
		{
			usart2send((uint8_t *)wifi_reset, 5);
			Flag.wifiReset = 0;
		}
		//Show_Chinese32(7,7,9,24,200,150,1);    //万
		//Show_Chinese32(7,7,8,24,200,150,1);     //指
		show_info(); // LCD显示
	}
}
